
<template>
	<div>
		<a-tree
			v-if="treeData.length > 0"
			showLine
			:virtual="true"
			v-model:expandedKeys="expandedKeys"
			v-model:selectedKeys="selectedKeys"
			:tree-data="treeData"
			ref="dataTreeRef"
			:load-data="loadData"
			@select="handleSelectChange"
		>
			<template #title="{ key: treeKey, title, id, type, dataSourceId, tableId, schemaId }">
				<a-dropdown :trigger="['contextmenu']">
					<span>{{ title }}</span>
					<template #overlay>
						<a-menu
							@click="({ key: action }) => handleContextMenu(action, title, id, type, dataSourceId, tableId, schemaId)"
						>
							<a-menu-item key="edit">编辑</a-menu-item>
							<a-menu-item key="add">新增</a-menu-item>
							<a-menu-item key="delete">删除</a-menu-item>
						</a-menu>
					</template>
				</a-dropdown>
			</template>
		</a-tree>
		<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />

		<a-modal v-model:open="tableInfo.visible" title="新增、修改表" @ok="addUpdateTable" @cancel="cancelTableOpen">
			<a-form ref="formRef" :model="tableInfo" inline>
				<a-form-item label="tableName">
					<a-input type="text" v-model:value="tableInfo.tableName" placeholder="请输入表名称"> </a-input>
				</a-form-item>
			</a-form>
		</a-modal>

		<a-modal
			v-model:open="indexInfo.visible"
			title="新增、修改索引"
			:closable="false"
			@ok="addUpdateIndex"
			@cancel="cancelindexOpen"
		>
			<a-form ref="formInline" :model="indexInfo" inline>
				<a-form-item label="indexName">
					<a-input type="text" v-model:value="indexInfo.indexName" placeholder="请输入索引名称"> </a-input>
				</a-form-item>
				<a-form-item label="fieldList">
					<a-select v-model:value="indexInfo.fieldList" clearable multiple filterable>
						<a-select-option v-for="item in indexFieldList" :value="item.columnId" :key="item.columnId"
							>{{ item.columnId }}
						</a-select-option>
					</a-select>
				</a-form-item>
			</a-form>
		</a-modal>
	</div>
</template>
<script setup>
import dataSourceApi from '@/api/datasource/dataSourceApi'
import { message } from 'ant-design-vue'
import { Empty } from 'ant-design-vue'

const props = defineProps({
	dataSourceId: {
		type: String
	},
	viewTableFlag: {
		type: Boolean,
		default: true
	},
	schemaId: {
		type: String
	},
	tableName: {
		type: String
	},
	selectChange: {
		type: Function
	},
	editor: {
		type: Boolean,
		default: true
	},
	type: {
		type: String
	}
})

const expandedKeys = ref([])
const selectedKeys = ref([])
const treeData = ref([])

const dataSource = ref({})

const contextData = ref({})

const dataTreeRef = ref()

const { proxy } = getCurrentInstance()

const tableInfo = ref({
	visible: false,
	tableName: null
})

const indexInfo = ref({
	visible: false,
	indexName: null,
	fieldList: []
})

watch(
	() => props.dataSourceId,
	async (newValue, oldValue) => {
		await init()
	}
)
onMounted(() => {
	init()
})
const init = async () => {
	treeData.value = []
	dataSource.value = null
	await queryById(props.dataSourceId, props.type)
	await setDatabase()
}

const handleContextMenu = (action, title, id, type, dataSourceId, tableId, schemaId) => {
	contextData.value = {
		id,
		type,
		title,
		dataSourceId,
		tableId,
		schemaId
	}
	if (action == 'edit') {
		handleContextMenuEdit()
	} else if (action == 'add') {
		handleContextMenuAdd()
	} else if (action == 'delete') {
		handleContextMenuDelete()
	}
}

const setDatabase = async () => {
	treeData.value = []
	if (!dataSource.value) {
		return
	}
	const s = {
		title: dataSource.value.datasourceName,
		id: dataSource.value.id,
		loading: false,
		key: dataSource.value.id,
		contextmenu: props.editor,
		type: 'dataSource',
		children: []
	}
	treeData.value.push(s)

	if (props.schemaId) {
		//展开dataSource
		expandedKeys.value.push(dataSource.value.id)
		expandedKeys.value.push(props.schemaId)
		selectedKeys.value.push(props.schemaId)
		if (props.tableName) {
			selectedKeys.value = []
			expandedKeys.value.push(props.schemaId + '_' + 'tables')
			selectedKeys.value.push(props.tableName)
		}
	} else if (props.tableName) {
		//s.expand = true;
		expandedKeys.value.push(dataSource.value.id)
		expandedKeys.value.push(props.tableName)
		selectedKeys.value = []
		selectedKeys.value.push(props.tableName)
		//todo
	}
}
const queryById = async (id, type) => {
	if (!id) {
		return
	}
	dataSource.value = await dataSourceApi.queryById({ id, type })
}

const loadData = async (item) => {
	return new Promise(async (resolve) => {
		if (item.type == 'dataSource') {
			const d = await queryCatalogList(item.id)
			if (d && d.length <= 0) {
				// item.noSchemaFlag = true;
				item.dataSourceId = item.id
				item.id = null
				item.type = 'catalog'
				loadData(item)
				resolve()
				return
			}
			item.dataRef.children = d
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'catalog') {
			const d = await querySchemaList(item.dataSourceId || item.id)
			if (d && d.length <= 0) {
				// item.noSchemaFlag = true;
				item.type = 'schema'
				// item.id=null;
				loadData(item)
				resolve()
				return
			}
			item.dataRef.children = d
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'schema') {
			if (!props.viewTableFlag) {
				resolve()
				return
			}
			// const schema = await queryTableList(item.dataSourceId,item.id);
			const d = [
				{
					title: 'tables',
					id: item.id + '_' + 'tables',
					schemaId: item.id,
					key: item.id + '_' + 'tables',
					dataSourceId: item.dataSourceId,
					loading: false,
					contextmenu: props.editor,
					type: 'tables',
					children: []
				}
			]

			item.dataRef.children = d
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'tables') {
			const schema = await queryTableList(item.dataSourceId, item.schemaId)
			item.dataRef.children = schema
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'table') {
			const d = [
				{
					title: 'columns',
					id: 'columns',
					schemaId: item.schemaId,
					tableId: item.title,
					dataSourceId: item.dataSourceId,
					loading: false,
					contextmenu: props.editor,
					type: 'columns',
					children: []
				},
				{
					title: 'keys',
					id: 'keys',
					tableId: item.title,
					schemaId: item.schemaId,
					dataSourceId: item.dataSourceId,
					loading: false,
					contextmenu: props.editor,
					type: 'keys',
					children: []
				},
				{
					title: 'indexes',
					id: 'indexes',
					tableId: item.title,
					schemaId: item.schemaId,
					dataSourceId: item.dataSourceId,
					loading: false,
					contextmenu: props.editor,
					type: 'indexes',
					children: []
				}
			]
			item.dataRef.children = d
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'columns') {
			const d = await queryTableFieldList(item.dataSourceId, item.tableId, item.schemaId)
			item.dataRef.children = d
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'column') {
			item.dataRef.children = []
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'indexes') {
			const schema = await queryTableIndexList(item.dataSourceId, item.tableId, item.schemaId)
			item.dataRef.children = schema
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'index') {
			item.dataRef.children = []
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'keys') {
			const schema = await queryTableKeysList(item.dataSourceId, item.tableId, item.schemaId)
			item.dataRef.children = schema
			treeData.value = [...treeData.value]
			resolve()
		} else if (item.type == 'key') {
			item.dataRef.children = []
			treeData.value = [...treeData.value]
			resolve()
		}
	})
}

const queryTableKeysList = async (id, tableName, catalogName) => {
	//查询表
	var s = await dataSourceApi.queryTableKeysList({
		id: id,
		catalogName: catalogName,
		tableName: tableName,
		type: props.type
	})
	if (s) {
		var d = []
		s.forEach((v) => {
			d.push({
				columnId: v.columnName,
				title: v.isPrimary ? 'PRIMARY ' + v.columnName : v.columnName,
				dataSourceId: id,
				loading: false,
				isLeaf: true,
				contextmenu: props.editor,
				type: 'key',
				children: []
			})
		})
		return d
	}
	return []
}

const queryTableIndexList = async (id, tableName, catalogName) => {
	//查询表
	var s = await dataSourceApi.queryTableIndexList({
		id: id,
		catalogName: catalogName,
		tableName: tableName,
		type: props.type
	})
	if (s) {
		var d = []
		s.forEach((v) => {
			let str = ''
			for (let i = 0; i < v.columnNameList.length; i++) {
				if (i == v.columnNameList.length - 1) {
					str = str + v.columnNameList[i]
				} else {
					str = str + v.columnNameList[i] + ','
				}
			}
			d.push({
				indexId: v.indexName,
				title: v.indexName + '(' + str + ')',
				dataSourceId: id,
				tableId: tableName,
				schemaId: catalogName,
				loading: false,
				isLeaf: true,
				contextmenu: props.editor,
				type: 'index',
				children: []
			})
		})
		return d
	}
	return []
}

const queryTableFieldList = async (id, tableName, catalogName) => {
	//查询表
	var s = await dataSourceApi.queryTableFieldList({
		id: id,
		catalogName: catalogName,
		tableName: tableName,
		type: props.type
	})
	if (s) {
		var d = []
		s.forEach((v) => {
			d.push({
				columnId: v.columnName,
				title: v.columnName + ' ' + v.originalColumnTypeName + '(' + v.columnLength + ')',
				dataSourceId: id,
				loading: false,
				isLeaf: true,
				contextmenu: props.editor,
				type: 'column',
				children: []
			})
		})
		return d
	}
	return []
}

const queryTableList = async (id, catalogName) => {
	//查询表
	var s = await dataSourceApi.queryTableList({
		id: id,
		catalogName: catalogName,
		type: props.type
	})
	if (s) {
		var d = []
		s.forEach((v) => {
			d.push({
				title: v,
				id: v,
				key: v,
				dataSourceId: id,
				schemaId: catalogName,
				loading: false,
				contextmenu: props.editor,
				type: 'table',
				children: []
			})
		})
		return d
	}
	return []
}

const queryCatalogList = async (id) => {
	var s = await dataSourceApi.queryCatalogList({
		id: id,
		type: props.type
	})
	if (s) {
		var d = []
		s.forEach((v) => {
			d.push({
				title: v,
				id: v,
				dataSourceId: id,
				key: v,
				loading: false,
				contextmenu: props.editor,
				type: 'catalog',
				children: []
			})
		})
		return d
	}
	return []
}

const queryTableDdl = async (tableName) => {
	let d = await dataSourceApi.queryTableDdl({
		id: proxy.$route.query.id,
		tableName: tableName,
		type: props.type
	})
	message.success(d)
}

const querySchemaList = async (id) => {
	var s = await dataSourceApi.querySchemaList({
		id: id,
		type: props.type
	})
	if (s) {
		var d = []
		s.forEach((v) => {
			d.push({
				title: v,
				id: v,
				dataSourceId: id,
				loading: false,
				contextmenu: props.editor,
				type: 'schema',
				children: []
			})
		})
		return d
	}
	return []
}

const handleContextMenuEdit = () => {
	if (!contextData.value) {
		return
	}

	if (contextData.value.type == 'dataSource') {
		proxy.$message.error('不允许编辑')
		return
	}
	if (contextData.value.type == 'catalog') {
		proxy.$message.error('不允许编辑')
		return
	}
	if (contextData.value.type == 'schema') {
		proxy.$message.error('不允许编辑')
		return
	}
	if (contextData.value.type == 'tables') {
		proxy.$message.error('不允许编辑')
		return
	}
	if (contextData.value.type == 'table') {
		tableInfo.value.visible = true
		tableInfo.value.tableName = contextData.value.title
		return
	}
	if (contextData.value.type == 'keys') {
		proxy.$message.error('不允许编辑')
		return
	}
	if (contextData.value.type == 'columns') {
		proxy.$message.error('不允许编辑')
		return
	}
	if (contextData.value.type == 'indexes') {
		proxy.$message.error('不允许编辑')
		return
	}
}

const indexFieldList = ref([])

const handleContextMenuAdd = async () => {
	if (!contextData.value) {
		return
	}
	if (contextData.value.type == 'dataSource') {
		proxy.$message.error('不允许新增')
		return
	}
	if (contextData.value.type == 'catalog') {
		proxy.$message.error('不允许新增')
		return
	}
	if (contextData.value.type == 'schema') {
		proxy.$message.error('不允许新增')
		return
	}
	if (contextData.value.type == 'tables') {
		tableInfo.value.visible = true
		return
	}
	if (contextData.value.type == 'table') {
		proxy.$message.error('不允许新增')
		return
	}
	if (contextData.value.type == 'keys') {
		proxy.$message.error('不允许新增')
		return
	}
	if (contextData.value.type == 'columns') {
		proxy.$message.error('不允许新增')
		return
	}
	if (contextData.value.type == 'indexes') {
		indexInfo.value.visible = true
		indexFieldList.value = await queryTableFieldList(
			contextData.value.dataSourceId,
			contextData.value.tableId,
			contextData.value.schemaId
		)
		return
	}
}

const handleContextMenuDelete = () => {
	if (!contextData.value) {
		return
	}
	if (contextData.value.type == 'dataSource') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'catalog') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'schema') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'tables') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'table') {
		removeTable()
		return
	}
	if (contextData.value.type == 'keys') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'columns') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'indexes') {
		proxy.$message.error('不允许删除')
		return
	}
	if (contextData.value.type == 'index') {
		dropIndex()
		return
	}
}
const dropIndex = async () => {
	await dataSourceApi.dropIndex({
		indexName: contextData.value.indexId,
		tableName: contextData.value.tableId,
		id: contextData.value.dataSourceId,
		catalogName: contextData.value.schemaId,
		type: props.type
	})
	proxy.$message.success('删除成功')

	const s = findParentRow(treeData.value, treeData.value)
	s.children = []
	s.expand = false
}
const removeTable = async () => {
	await dataSourceApi.removeTable({
		tableName: contextData.value.title,
		id: contextData.value.dataSourceId,
		catalogName: contextData.value.schemaId,
		type: props.type
	})
	proxy.$message.success('删除成功')
	// contextData.value.children = [];
	// contextData.value.expand = false;

	const s = findParentRow(treeData.value, treeData.value)
	s.children = []
	s.expand = false
}
const findParentRow = (treeData, parentData) => {
	if (!treeData || treeData.length <= 0) {
		return null
	}
	let res = null
	for (const data of treeData) {
		if (data.id == contextData.value.id) {
			res = parentData
			break
		}

		const bres = findParentRow(data.children, data)
		if (bres) {
			res = bres
			break
		}
	}
	return res
}

const handleSelectChange = (selectedKeys, e) => {
	//选中
	if (props.selectChange) {
		props.selectChange(e.node.dataRef)
	}
}

const addUpdateTable = async () => {
	await dataSourceApi.addUpdateTable({
		tableName: tableInfo.value.tableName,
		sourceTableName: contextData.value.type == 'table' ? contextData.value.title : null,
		id: contextData.value.dataSourceId,
		catalogName: contextData.value.schemaId,
		type: props.type
	})

	if (contextData.value.type == 'table') {
		const s = findParentRow(treeData.value, treeData.value)
		s.children = []
		s.expand = false
	} else {
		contextData.value.children = []
		contextData.value.expand = false
	}

	tableInfo.value.tableName = null
	tableInfo.value.visible = false
}

const addUpdateIndex = async () => {
	await dataSourceApi.addUpdateIndex({
		indexName: indexInfo.value.indexName,
		tableName: contextData.value.tableId,
		sourceIndexName: contextData.value.type == 'index' ? contextData.value.title : null,
		id: contextData.value.dataSourceId,
		catalogName: contextData.value.schemaId,
		fieldNameList: indexInfo.value.fieldList,
		type: props.type
	})

	if (contextData.value.type == 'index') {
		const s = findParentRow(treeData.value, treeData.value)
		s.children = []
		s.expand = false
	} else {
		contextData.value.children = []
		contextData.value.expand = false
	}

	indexInfo.value.indexName = null
	indexInfo.value.fieldList = []
	indexInfo.value.visible = false
}
const cancelTableOpen = () => {
	tableInfo.tableName = null
	tableInfo.visible = false
}
const cancelindexOpen = () => {
	indexInfo.indexName = null
	indexInfo.visible = false
}
</script>


<style scoped></style>
